/**
 * @file oeuvre.h
 * @brief Fichier d'entête du module oeuvre.
 *
 * @author Rachid Delory, Florian Bernard, Keita Mamadou
 */
#ifndef H_OEUVRE_H
#define H_OEUVRE_H

/* ********************************************************************* */
/*                                                                       */
/*                       Librairies de l'oeuvre                          */
/*                                                                       */
/* ********************************************************************* */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "film.h"
#include "musique.h"
#include "livre.h"
#include "date.h"
#include "label.h"
#include "public.h"
#include "ensemble.h"
#include "langue.h"
#include "genre.h"
#include "activite.h"

/* ********************************************************************* */
/*                                                                       */
/*                        Définitions de types                           */
/*                                                                       */
/* ********************************************************************* */
/**
 * @enum TYPEMEDIA
 * @brief Tout les types qu'une oeuvre peut avoir
 */
typedef enum
  {
    AUCUN_OEU = 0,
    FILM_OEU = 1,
    MUSIQUE_OEU = 2,
    LIVRE_OEU = 3,
    REGROUPEMENT_OEU = 4,
    VIDE_OEU = 5
  } TYPEMEDIA;

/**
 * @struct sOeuvre
 * @brief Structure utilisée pour la gestion d'une oeuvre.
 *
 * Cette structure est utilisée pour gérer une oeuvre.
 Les champs de cette structure doivent être modifiés ou lus par les accesseurs et mutateurs.
 */

struct sOeuvre {
  unsigned int id;/** Identification De l'Oeuvre */
  unsigned int nbVisio;/** Nombre De Vision */
  char * titre;/** Titre De l'Oeuvre */
  unsigned int type;/** Type De l'Oeuvre */
  char * illustration;/** Chemin Vers l'Illustration */
  char * commentaire;/** Commentaire Sur l'Oeuvre */
  char * lienMedia;/** Lien Vers Le Media */
  Date * dateSortie;/** Date De sortie De l'Oeuvre */
  Label * pLabel;/** Label de l'Oeuvre Avec Pointeur Vers Oeuvre */
  int public;/** Enum de type public correspondant au droit de vision de l'oeuvre */
  Ensemble* eLangue;/** Langue De l'Oeuvre Avec Pointeur Vers Ensemble */
  Ensemble * eGenre;/** Genre De l'Oeuvre Avec Pointeur Vers Ensemble */
  Ensemble * eCollaborateur;/** lien Vers Ensemble */
  void * media;/** Pointeur générique sur la structure associé à l'oeuvre en fonction de son type */
  char maj;
  char sup;
} ;

/**
 * @typedef Oeuvre
 * @brief Redéfinit la structure sOeuvre.
 */
typedef struct sOeuvre Oeuvre ;

/* ********************************************************************* */
/*                                                                       */
/*                 Fonctions relatives aux oeuvres                        */
/*                                                                       */
/* ********************************************************************* */

/**
 * @fn void init_Oeu(Oeuvre *oeuvre);
 * @brief Initialise une oeuvre
 * 
 * @param[in,out] oeuvre
 */
void init_Oeu(Oeuvre * oeuvre) ;

/**
 * @fn void liberer_Oeu(Oeuvre *oeuvre);
 * @brief Libere une oeuvre
 *
 * @param[in,out] oeuvre
 */
void liberer_Oeu(Oeuvre *oeuvre);

/**
 * @fn Oeuvre *creer_Oeu() ;
 * @brief Initialise une oeuvre.
 *
 * @return un pointeur sur une Oeuvre initialisé en mémoire
 */
void *creer_Oeu() ;


/**
 * @fn void detruire_Oeu(Oeuvre *pOeuvre)
 * @brief Libere la structure oeuvre.
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre à detruir.
 */
void detruire_Oeu(Oeuvre **pOeuvre) ;

/**
 * @fn void copier_Oeu(Oeuvre *dest, const Oeuvre *src);
 * @brief Copie le contenu de src dans dest
 *
 * @param[in,out] dest est l'oeuvre de destination
 * @param src
 */
void copier_Oeu(Oeuvre **dest, const Oeuvre *src);

/* ********************************************************************* */
/*                                                                       */
/*           Accesseurs et Mutateurs de la structure Oeuvre               */
/*                                                                       */
/* ********************************************************************* */

/**
 * @fn unsigned int getId_Oeu(const Oeuvre *pOeuvre)
 * @brief Récupère l'ID De l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return la valeur de l'ID demandée.
 */
unsigned int getId_Oeu(const Oeuvre *pOeuvre) ;


/**
 * @fn void setId_Oeu(Oeuvre *pOeuvre, const int id)
 * @brief Modifie la Valeur ID de coordonnée (id).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param id coordonnée id de l'Oeuvre à modifier.
 */
void setId_Oeu(Oeuvre *pOeuvre, const unsigned int id) ;

/**
 * @fn unsigned int getNbVisio_Oeu(const Oeuvre *pOeuvre)
 * @brief Récupère le nombre De Vision De l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return la valeur de NbVisio demandée.
 */
unsigned int getNbVisio_Oeu(const Oeuvre *pOeuvre) ;


/**
 * @fn void setNbVisio_Oeu(Oeuvre *pOeuvre, const int nbVisio)
 * @brief Modifie la Valeur nbVisio de coordonnée (nbVisio).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param nbVisio coordonnée nbVisio de l'Oeuvre à modifier.
 */
void setNbVisio_Oeu(Oeuvre *pOeuvre, const int nbVisio) ;


/**
 * @fn unsigned char * getTitre_Oeu(const Oeuvre *pOeuvre)
 * @brief Récupère le titre De l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return le titre de l'Oeuvre.
 */
char *getTitre_Oeu(const Oeuvre *pOeuvre) ;


/**
 * @fn void setTitre_Oeu(Oeuvre *pOeuvre,const char * titre)
 * @brief Modifie le titre de coordonnée (titre).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param titre Coordonnée titre de l'Oeuvre à modifier.
 */
void setTitre_Oeu(Oeuvre *pOeuvre, const char * titre) ;

/**
 * @fn unsinged int getType_Oeu(const Oeuvre *pOeuvre)
 * @brief Récupère le type de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return Le type de l'Oeuvre demandée.
 */
unsigned int getType_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void setType_Oeu(Oeuvre *pOeuvre, const unsigned int type)
 * @brief Modifie le type de coordonnée (type).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param[in, out] type coordonnée type de l'Oeuvre à modifier.
 */
void setType_Oeu(Oeuvre *pOeuvre, const unsigned int type) ;

 /**
 * @fn char * getIllustration_Oeu(const Oeuvre *pOeuvre)
 * @brief Récupère l'illustration de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return l'illustration de l'Oeuvre demandée.
 */
char * getIllustration_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void setIllustration_Oeu(Oeuvre *pOeuvre, const char * illustration)
 * @brief Modifie l'illustration de coordonnée (illustration).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param[in, out] illustration coordonnée illustration de l'Oeuvre à modifier.
 */
void setIllustration_Oeu(Oeuvre *pOeuvre, const char *illustration) ;

 /**
 * @fn char * getCommentaire_Oeu(const Oeuvre *pOeuvre) ;
 * @brief Récupère le commentaire de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return Le commentaire de l'Oeuvre demandée.
 */
char * getCommentaire_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void setCommentaire_Oeu(Oeuvre *pOeuvre, const char * commentaire) ;
 * @brief Modifie le commentaire de coordonnée (commentaire).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param[in, out] commentaire coordonnée commentaire de l'Oeuvre à modifier.
 */
void setCommentaire_Oeu(Oeuvre *pOeuvre, const char * commentaire) ;

/**
 * @fn char * getLienMedia_Oeu(const Oeuvre *pOeuvre) ;
 * @brief Récupère le lien de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return unsigned char Le lien de l'Oeuvre demandée.
 */
char * getLienMedia_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void setLienMedia_Oeu(Oeuvre *pOeuvre, const char * lien) ;
 * @brief Modifie le lien de coordonnée (lien).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param[in, out] lien coordonnée lien de l'Oeuvre à modifier.
 */
void setLienMedia_Oeu(Oeuvre *pOeuvre, const char * lien) ;

/**
 * @fn Date * getDateSortie_Oeu(const Oeuvre *pOeuvre)
 * @brief Récupère la date de sortie de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return La date de sortie de l'Oeuvre demandée.
 */
Date * getDateSortie_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void setDateSortie_Oeu(Oeuvre *pOeuvre, const Date * date)
 * @brief Modifie la date de sortie de coordonnée (date).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param[in, out] date Coordonnée date de l'Oeuvre à modifier.
 */
void setDateSortie_Oeu(Oeuvre *pOeuvre, const Date * date) ;

/**
 * @fn Label * getLabel_Oeu(const Oeuvre *pOeuvre) ;
 * @brief Récupère le label de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return Le label de l'Oeuvre demandée.
 */
Label * getLabel_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void setLabel_Oeu(Oeuvre *pOeuvre, const Label *pLabel) ;
 * @brief Modifie le label de coordonnée (pLabel).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param[in, out] pLabel Pointeur vers Label de l'Oeuvre à modifier.
 */
void setLabel_Oeu(Oeuvre *pOeuvre, const Label *pLabel) ;

/**
 * @fn int getPublic_Oeu(const Oeuvre *pOeuvre) ;
 * @brief Récupère le public de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return Le type de public de l'Oeuvre demandée.
 */
int getPublic_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void setPublic_Oeu(Oeuvre *pOeuvre, const int public)
 * @brief Modifie le public de coordonnée (pPublic).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param[in, out] pPublic Pointeur vers Public de l'Oeuvre à modifier.
 */
void setPublic_Oeu(Oeuvre *pOeuvre, const int public) ;

/**
 * @fn void * getMedia_Oeu(const Oeuvre *pOeuvre)
 * @brief Récupère le media de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return Le media de l'Oeuvre demandée.
 */
void * getMedia_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void setMedia_Oeu(Oeuvre *pOeuvre, void *media)
 * @brief Modifie le media de coordonnée (media).
 *
 * @param[in, out] pOeuvre Pointeur vers l'oeuvre.
 * @param[in, out] media de coordonnée media de l'Oeuvre à modifier.
 */
void setMedia_Oeu(Oeuvre *pOeuvre, void * media, void (*copier)()) ;

/**
 * @fn Ensemble * getEnsembleGenre_Oeu(const Oeuvre *pOeuvre) ;
 * @brief Récupère l'ensemble de genre de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return L'ensemble de genre de l'Oeuvre demandée.
 */
Ensemble * getEnsembleGenre_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn Ensemble * getEnsembleLangue_Oeu(const Oeuvre *pOeuvre) ;
 * @brief Récupère l'ensemble de langue de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return L'ensemble de langue de l'Oeuvre demandée.
 */
Ensemble * getEnsembleLangue_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn Ensemble * getEnsembleCollaborateur_Oeu(const Oeuvre *pOeuvre) ;
 * @brief Récupère l'ensemble de collaborateur de l'Oeuvre.
 *
 * @param pOeuvre Pointeur vers l'oeuvre.
 * @return L'ensemble de collaborateur de l'Oeuvre demandée.
 */
Ensemble * getEnsembleCollaborateur_Oeu(const Oeuvre *pOeuvre) ;

/**
 * @fn void ajouterGenre_Oeu(Oeuvre *oeuvre, Genre *genre)
 * @brief Ajoute un genre dans l'ensemble des genres appartenant à l'oeuvre
 *
 * @param oeuvre Pointeur vers l'oeuvre.
 * @param genre Pointeur vers le genre.
 */
void ajouterGenre_Oeu(Oeuvre *oeuvre, Genre *genre) ;

/**
 * @fn void ajouterLangue_Oeu(Oeuvre *oeuvre, Langue *langue)
 * @brief Ajoute un langue dans l'ensemble des langues appartenant à l'oeuvre
 *
 * @param oeuvre Pointeur vers l'oeuvre.
 * @param langue Pointeur vers la langue.
 */
void ajouterLangue_Oeu(Oeuvre *oeuvre, Langue *langue) ;

/**
 * @fn void ajouterCollaborateur_Oeu(Oeuvre *oeuvre, Activite *collaborateur)
 * @brief Ajoute un collaborateur dans l'ensemble des collaborateurs appartenant à l'oeuvre
 *
 * @param oeuvre Pointeur vers l'oeuvre.
 * @param collaborateur Pointeur vers le collaborateur.
 */
void ajouterCollaborateur_Oeu(Oeuvre *oeuvre, struct sActivite *collaborateur) ;


/**
 * @fn void setMaj_Oeu(Oeuvre *ptr, const char b);
 * @brief Set le besoin de faire une mise à jour, ou pas
 * 
 * @param[in,out] ptr
 * @parm b
 */
void setMaj_Oeu(Oeuvre *ptr, const char b);

/**
 * @fn char getMaj_Oeu(const Oeuvre *ptr);
 * @brief Retourne 0 si pas besoin de faire la mise à jour, et 1 sinon
 *
 * @param ptr
 * @return Comme un boolean
 */
char getMaj_Oeu(const Oeuvre *ptr);

/**
 * @fn void setSup_Oeu(Oeuvre *ptr, const char b);
 * @brief Set le besoin de le supprimer, ou pas
 * 
 * @param[in,out] ptr
 * @parm b
 */
void setSup_Oeu(Oeuvre *ptr, const char b);

/**
 * @fn char getSup_Oeu(const Oeuvre *ptr);
 * @brief Retourne 0 si pas besoin de le supprimer, et 1 sinon
 *
 * @param ptr
 * @return Comme un boolean
 */
char getSup_Oeu(const Oeuvre *ptr);

/* *********************************************************************
                           Test de regression                         
********************************************************************* */

/**
 * @fn void regression_Oeu()
 * @brief Teste toutes les fonctions du module oeuvre.h
 */
void regression_Oeu() ;

#endif
